package com.xhwl.centiotdata.suppliersystem.keytopLocal;


import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xhwl.centiotdata.pojo.constant.KeyTopLocalConstant;
import com.xhwl.centiotdata.pojo.constant.StrConstant;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.common.exception.ApplicationException;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.utils.ChkUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author msy
 */
@Slf4j
@Service
public class GeneralKeyTopLocalHandler {

    @Autowired
    private RedisUtils redisUtils;

    private String getToken(Integer projectId, Integer productId, String ipAndPort, String account, String password) {
        ReentrantLock lock = new ReentrantLock();
        String token;
        lock.lock();
        try {
            String key = new StringBuffer(StrConstant.SUPPLIER_SYSTEM_TOKEN).append("-").append(projectId).append("-").append(productId).toString();
            Object value = redisUtils.get(key);
            if (value == null) {
                // 1、登录鉴权挑战
                JSONObject data = challenge(ipAndPort);
                if(ChkUtil.isNull(data)) {
                    throw new BusinessException("登录挑战失败!");
                }
                // 2、登录
                token = login(data, ipAndPort, account, password);
                // 设置或更新过期时间
                redisUtils.setWithMinute(key, token, 10);
            } else {
                token = (String) value;
            }
        } catch (Exception e) {
            log.error("getAccessToken exception,projectId:{}", projectId);
            e.printStackTrace();
            throw new ApplicationException();
        } finally {
            lock.unlock();
        }
        return token;
    }


    /**
     * 登录鉴权挑战
     * @return
     */
    private JSONObject challenge(String ipAndPort) {
        String responseJson = null;
        try {
            responseJson = HttpRequest.post(ipAndPort + KeyTopLocalConstant.CHALLENGE).execute().body();
        } catch (Exception e) {
            log.error("登录鉴权挑战request failed!!!");
            e.printStackTrace();
            throw new ApplicationException();
        }

        if(ChkUtil.isNull(responseJson)) {
            log.error("responseJson is null !!!");
            throw new BusinessException();
        }

        JSONObject result = new JSONObject(responseJson);
        if(KeyTopLocalConstant.SUCCESS_CODE.equals(result.getInt("resultCode"))) {
            JSONObject data = result.getJSONObject("data");
            return data;
        }
        log.error("登录鉴权挑战失败： {}", result);
        return null;
    }

    private String login(JSONObject challengeResult, String ipAndPort, String account, String password) {
        String challengeId = challengeResult.getStr("challengeId");
        String challenge = challengeResult.getStr("challenge");
        String salt = challengeResult.getStr("salt");
        // 加密后的密码
        String secretPassword = DigestUtil.md5Hex(DigestUtil.md5Hex(password) + salt + challenge);

        Map<String, Object> params = new HashMap<>();
        params.put("account", account);
        params.put("challengeId", challengeId);
        params.put("password", secretPassword);

        String responseJson = null;
        try {
            responseJson = HttpRequest.post(ipAndPort + KeyTopLocalConstant.LOGIN)
                    .body(JSONUtil.toJsonStr(params)).execute().body();
        } catch (Exception e) {
            log.error("request failed!!!  param: {}", JSONUtil.toJsonStr(params));
            e.printStackTrace();
            throw new ApplicationException();
        }

        if(ChkUtil.isNull(responseJson)) {
            log.error("responseJson is null !!!   param: {}", JSONUtil.toJsonStr(params));
            throw new BusinessException();
        }
        JSONObject result = new JSONObject(responseJson);
        if(KeyTopLocalConstant.SUCCESS_CODE.equals(result.getInt("resultCode"))) {
            JSONObject data = result.getJSONObject("data");
            String token = data.getStr("token");
            return token;
        }
        log.error("登录失败: {}", result);
        return null;
    }

    public JSONObject post(String api, Map params, Integer projectId, Integer productId, String ipAndPort, String account, String password) {
        String token = this.getToken(projectId, productId, ipAndPort, account, password);
        if(ChkUtil.isNull(token)) {
            return null;
        }
        HttpRequest httpRequest = HttpRequest.post(ipAndPort + api).header("token", token).header("Content-Type", "application/json");
        if (params != null) {
            httpRequest.body(JSONUtil.toJsonStr(params));
        } else {
            httpRequest.body(JSONUtil.toJsonStr(new JSONObject()));
        }
        String responseJson = null;
        try {
            responseJson = httpRequest.execute().body();
        } catch (Exception e) {
            log.error("request failed!!!  param: {}", JSONUtil.toJsonStr(params));
            e.printStackTrace();
            throw new ApplicationException();
        }
        JSONObject result = new JSONObject(responseJson);
        if(!KeyTopLocalConstant.SUCCESS_CODE.equals(result.getInt("resultCode"))) {
            log.error("操作失败： params: {} ,  result: {}", JSONUtil.toJsonStr(params), result);
            throw new BusinessException();
        }
        log.info("调用成功： {}", result);
        return result;
    }

}
